package pizza.util; /** an abstract class for implementations of the Enumeration interface */ public abstract class Enumerator<A> implements Enumeration<A> { /** the Enumeration methods */ public abstract boolean hasMoreElements(); public abstract A nextElement(); /** concat another enumerator, to be called when this one is done */ public Enumerator<A> concat(Enumerator<A> rest) { return new CompositeEnumerator(this, rest); } /** return enumerator that yields `f' applied to each element * of this enumerator */ public <B> Enumerator<B> map((A)->B f) { return new MapEnumerator(f, this); } /** return elements of this enumerator as long as predicate `p' is true */ public Enumerator<A> takeWhile((A)->boolean p) { return new TakeWhileEnumerator(p, this); } /** return enumerator that starts with the first element of this * enumerator for which `p' holds, and then continues with all * subsequent elements of this enumerator */ public Enumerator<A> dropWhile((A)->boolean p) { return new DropWhileEnumerator(p, this); } /** return enumerator that yields all element of this enumerator that * satisfy predicate `p'. */ public Enumerator<A> filter((A)->boolean p) { return new FilterEnumerator(p, this); } /** apply function `f' to all elements of this enumerator */ public <B> void forall((A)->B f) { while (hasMoreElements()) f(nextElement()); } /** reduce all elements of this enumerator with binary operation `f', * starting with `z'. Operations are grouped to the left. */ public <B> B reduceLeft(B z, (B,A)->B f) { while (hasMoreElements()) z = f(z, nextElement()); return z; } /** reduce all elements of this enumerator with binary operation `f', * starting with `z'. Operations are grouped to the right. */ public <B> B reduceRight((A,B)->B f, B z) { if (hasMoreElements()) return f(nextElement(), reduceRight(f, z)); else return z; } } /** A class for the empty enumerator, which yields no elements */ public class SingletonEnumerator<A> extends Enumerator<A> { A value; boolean unseen = true; public SingletonEnumerator(A value) { this.value = value; } public boolean hasMoreElements() { return unseen; } public A nextElement() { if (unseen) { unseen = false; return value; } else { throw new NoSuchElementException(); } } }